<?
    final class Principio_DHCP
    {
        private static function writeCompanyInPoolBlock(Principio_Model_CompanyInPool $model_company_in_pool, $dhcp_config_file)
        {
            fwrite($dhcp_config_file, "# @@@ BEGIN COMPANY IN POOL : CAPTION ".$model_company_in_pool->getCaption()."\n");
            fwrite($dhcp_config_file, "# @@@ BEGIN COMPANY IN POOL : PROXY ".$model_company_in_pool->getProxy()."\n");
            self::writeTypeInCompanyBlock($model_company_in_pool, $dhcp_config_file);
            fwrite($dhcp_config_file, "# @@@ END COMPANY IN POOL\n\n");
        }


        private static function writeBeginCompanyBlock(Principio_Model_Company_Abstract $model_company_abstract, $dhcp_config_file)
        {
            $dhcp_company = ($model_company_abstract->isPool() ? ("pool-".$model_company_abstract->getID()) : str_replace(".", "-", $model_company_abstract->getProxy()));

            fwrite($dhcp_config_file, "# BEGIN ".($model_company_abstract->isPool() ? "POOL" : "COMPANY")." : CAPTION [".$model_company_abstract->getCaption()."]\n");
            fwrite($dhcp_config_file, "# ".($model_company_abstract->isPool() ? ("IP/MASK ".$model_company_abstract->getIP()) : ("PROXY ".$model_company_abstract->getProxy()))."\n");
            fwrite($dhcp_config_file, "class \"".$dhcp_company."\" {\n\tmatch if (substring(vendor-class-identifier,1,7)=LINKSYS) and (binary-to-ascii(10,8,\".\", packet(24,4)) = \"".$model_company_abstract->getDefaultGW()."\");\n}\n\n");
            fwrite($dhcp_config_file, "subnet ".$model_company_abstract->getNetname()." netmask ".$model_company_abstract->getNetmask()." {\n");
            fwrite($dhcp_config_file, "\tpool {\n");
            fwrite($dhcp_config_file, "\t\tallow members of \"".$dhcp_company."\";\n");
            fwrite($dhcp_config_file, "\t\trange ".$model_company_abstract->getRangeFrom()." ".$model_company_abstract->getRangeTo().";\n");
            fwrite($dhcp_config_file, "\t}\n");
            fwrite($dhcp_config_file, "\toption domain-name-servers 87.249.32.2, 87.249.42.2;\n");
            fwrite($dhcp_config_file, "\toption routers ".$model_company_abstract->getDefaultGW().";\n");
            fwrite($dhcp_config_file, "\toption broadcast-address ".$model_company_abstract->getBroadcast().";\n");
            fwrite($dhcp_config_file, "\toption ntp-servers 87.249.32.1;\n");
            fwrite($dhcp_config_file, "\toption tftp-server-name \"172.16.251.70\";\n");
            fwrite($dhcp_config_file, "\toption tftp-server-address 172.16.251.70;\n\n");
        }


        private static function writeEndCompanyBlock(Principio_Model_Company_Abstract $model_company_abstract, $dhcp_config_file)
        {
            fwrite($dhcp_config_file, "}\n");
            fwrite($dhcp_config_file, "# END ".($model_company_abstract->isPool() ? "POOL" : "COMPANY")." : CAPTION [".$model_company_abstract->getCaption()."]\n\n\n\n\n\n\n");
        }


        private static function writeTypeInCompanyBlock(Principio_Model_Company_Abstract $model_company_abstract, $dhcp_config_file)
        {
            foreach ($model_company_abstract->getTypeInCompanyCollection() as $model_type_in_company)
            {
                fwrite($dhcp_config_file, "\n# ~~~ BEGIN TYPE [".$model_type_in_company->getModelType()->getCaption()."]\n");
                foreach ($model_type_in_company->getSpaCollection() as $model_spa)
                {
                    fwrite($dhcp_config_file, "\thost h".$model_spa->getSerial()." {\n");
                    fwrite($dhcp_config_file, "\t\thardware ethernet ".$model_spa->getMAC().";\n");
                    fwrite($dhcp_config_file, "\t\tfixed-address ".$model_spa->getIP().";\n");
                    fwrite($dhcp_config_file, "\t}\n");
                };
                fwrite($dhcp_config_file, "# ~~~ END TYPE [".$model_type_in_company->getModelType()->getCaption()."]\n\n");
            };
        }


        private static function writeCompanyOrPoolBlock(Principio_Model_Company_Abstract $model_company_abstract, $dhcp_config_file)
        {
            self::writeBeginCompanyBlock($model_company_abstract, $dhcp_config_file);
            if ($model_company_abstract->isPool())
            {
                foreach ($model_company_abstract->getCompanies() as $model_company_in_pool)
                    self::writeCompanyInPoolBlock($model_company_in_pool, $dhcp_config_file);
            };

            self::writeTypeInCompanyBlock($model_company_abstract, $dhcp_config_file);
            self::writeEndCompanyBlock($model_company_abstract, $dhcp_config_file);
        }


        public static function generate()
        {
            $model_option_dhcp_config_file = Principio_Model_SettingMapper::fetch(Principio_Model_SettingMapper::SETTING_DHCP_CONFIG_FILE);

            $dhcp_config_file = fopen($model_option_dhcp_config_file->getValue().".tmp", "wt");

            if ($dhcp_config_file === false)
                return Principio_Common::reportError("DHCPD: can't open [".$model_option_dhcp_config_file->getValue().".tmp] for writing.");

            fwrite($dhcp_config_file, "#\n# ATTENTION\n# THIS FILE WAS GENERATED BY PRINCIPIO\n# DO NOT EDIT THIS FILE - USE WEB\n#\n\n");

            foreach (Principio_Model_Company_AbstractMapper::getRoot() as $model_company_abstract)
                self::writeCompanyOrPoolBlock($model_company_abstract, $dhcp_config_file);

            fclose($dhcp_config_file);

            if (rename($model_option_dhcp_config_file->getValue(), $model_option_dhcp_config_file->getValue().".tmp2") === true)
            {
                if (rename($model_option_dhcp_config_file->getValue().".tmp", $model_option_dhcp_config_file->getValue()) === true)
                {
                    if (unlink($model_option_dhcp_config_file->getValue().".tmp2") === true)
                    {
                        $return_var = -1;
                        $output = array();
                        $dhcpd_restart = exec(Principio_Model_SettingMapper::fetch(Principio_Model_SettingMapper::SETTING_DHCP_RESTART_COMMAND)->getValue(), $output, $return_var);
                        if ($return_var != 0)
                        {
                            $lines = "";
                            foreach ($output as $line)
                                $lines .= $line."<br>";

                            Principio_Common::reportError("DHCP: restart failure.&nbsp;&nbsp;&nbsp;Return code: [".$return_var."].&nbsp;&nbsp;&nbsp;Last line: [".$dhcpd_restart."]<br>Output: [".$lines."]");
                        };
                    }
                    else
                        Principio_Common::reportError("DHCP: can't delete backup copy [".$model_option_dhcp_config_file->getValue().".tmp2]");
                }
                else
                {
                    Principio_Common::reportError("DHCP: can't rename [".$model_option_dhcp_config_file->getValue().".tmp] to [".$model_option_dhcp_config_file->getValue()."]");

                    if (rename($model_option_dhcp_config_file->getValue()."tmp2", $model_option_dhcp_config_file->getValue()) === false)
                        Principio_Common::reportError("DHCP: can't restore from backup [".$model_option_dhcp_config_file->getValue()."tmp2] to [".$model_option_dhcp_config_file->getValue()."]");
                };
            }
            else
                Principio_Common::reportError("DHCP: can't backup [".$model_option_dhcp_config_file->getValue()."] to [".$model_option_dhcp_config_file->getValue().".tmp2]");
        }
    }
?>